home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1994 / MacHack 1994.toast / MacHack™ 1987-1994 / MacHack™ '89 / Papers '89 / Horwat Papers / FactorLab < prev    next >
Encoding:
Text File  |  1989-06-13  |  16.8 KB  |  543 lines  |  [TEXT/CCL ]

  1. ;
  2. ;Prime-testing and factorization procedures
  3. ;
  4. ;Copyright 1987, 1989 Waldemar Horwat
  5. ;
  6. ;May 25, 1987.
  7. ;June 13, 1989.
  8. ;
  9.  
  10. ;
  11. ;This program contains a few interesting routines.
  12. ;First there are several routines for adding, subtracting, multiplying, and
  13. ;exponentiating numbers in modular arithmetic, as well as implementing Euclid's
  14. ;algorithm
  15. ;
  16. ;The next major section is a set of primality testers.  The main entry point
  17. ;is the prime? function, which tests whether a number is prime using a number of
  18. ;tests.
  19. ;
  20. ;The following section consists of factoring routines.  Use the factor function
  21. ;to completely factor a number.
  22. ;
  23. ;Finally, a demo of the RSA algorithm is included.  This algorithm should not be
  24. ;used for encryption purposes without checking the RSA patent.
  25. ;
  26.  
  27. ;This program is written in standard Common Lisp.  It works under Coral Common Lisp;
  28. ;it has not been tested on Pearl Lisp, which is a subset of Common Lisp.
  29.  
  30.  
  31. ;*************
  32. ;* Utilities *
  33. ;*************
  34.  
  35. (defun display* (&rest items)
  36.   (dolist (item items) (prin1 item) (princ " ")))
  37.  
  38. (defun some? (f l)
  39.   (declare (optimize speed))
  40.   (cond ((endp l) nil)
  41.         ((funcall f (car l)) t)
  42.         (t (some? f (cdr l)))))
  43.  
  44.  
  45. (proclaim '(inline square))
  46. (defun square (x) (* x x))
  47.  
  48.  
  49. ;;;Return three values x, y, and g such that ax+by=g=gcd(a,b).
  50. (defun euclid (a b)
  51.   (defun euclid-sub (x1 x3 y1 y3)
  52.     (if (zerop y3)
  53.       (cond
  54.        ((zerop x3) (values 0 0 0))
  55.        ((< x3 0) (euclid-sub (- x1) (- x3) y1 y3))
  56.        (t (values x1 (if (zerop b) 0 (/ (- x3 (* a x1)) b)) x3)))
  57.       (multiple-value-bind (q r) (floor x3 y3)
  58.         (euclid-sub y1 y3 (- x1 (* q y1)) r))))
  59.   (euclid-sub 1 a 0 b))
  60.  
  61. ;;; Compute the sum of the args modulo the modulus.
  62. (defmacro m+ (modulus &rest args)
  63.   `(mod (+ ,@args) ,modulus))
  64.  
  65. ;;; Compute the difference or negation of the args modulo the modulus.
  66. (defmacro m- (modulus &rest args)
  67.   `(mod (- ,@args) ,modulus))
  68.  
  69. ;;; Compute the product of the args modulo the modulus.
  70. (defmacro m* (modulus &rest args)
  71.   (cond ((null args) 1)
  72.         ((endp (cdr args)) (car args))
  73.         (t `(mod (* ,(car args) (m* ,modulus ,@(cdr args))) ,modulus))))
  74.  
  75. ;;; Compute the square of n modulo the modulus.
  76. (defun msquare (modulus n)
  77.   (mod (* n n) modulus))
  78.  
  79. ;;; Compute n^exp (mod modulus).  exp should be nonnegative.
  80. (defun mexpt (modulus n exp)
  81.   (cond ((zerop exp) 1)
  82.         ((evenp exp)
  83.          (msquare modulus (mexpt modulus n (floor exp 2))))
  84.         (t (m* modulus n (square (mexpt modulus n (floor exp 2)))))))
  85.  
  86.  
  87. (defun divisible? (n divisors)
  88.   (some? #'(lambda (d) (zerop (rem n d))) divisors))
  89.  
  90.  
  91.  
  92. ;*****************
  93. ;* Prime Testing *
  94. ;*****************
  95.  
  96.  
  97. ;Return a list containing the n smallest primes.
  98. (defun n-smallest-primes (n)
  99.   (defun next-n-primes (p n primes)
  100.     (cond ((= n 0) primes)
  101.           ((divisible? p primes) (next-n-primes (+ 2 p) n primes))
  102.           (t (next-n-primes (+ 2 p) (1- n) (nconc primes (list p))))))
  103.   (cond ((<= n 0) nil)
  104.         ((= n 1) '(2))
  105.         (t (next-n-primes 3 (- n 1) (list 2)))))
  106.  
  107. (defvar small-primes (n-smallest-primes 30))
  108.  
  109. ;
  110. ;This is a quick primality test that checks that p contains no small factors.
  111. ;This test returns () if p is not a prime, t if it is, and maybe if it is
  112. ;likely a prime.
  113. ;
  114.  
  115. (defun prime0p (p)
  116.   (prime0-check p small-primes))
  117.  
  118. (defun prime0-check (p primes)
  119.   (cond ((< p 2) nil)
  120.         ((endp primes) 'maybe)
  121.         ((> (square (car primes)) p) t)
  122.         ((zerop (rem p (car primes))) nil)
  123.         (t (prime0-check p (cdr primes)))))
  124.  
  125.  
  126.  
  127. ;
  128. ;This is a quick primality test that checks that x^p-1=1 (mod p), where p
  129. ;is the suspect prime and x is a small number.
  130. ;This test returns nil if p is not a prime, t if it is, and maybe if it is
  131. ;likely a prime.
  132. ;
  133. ;This test is no longer used because it might consistently fail on Carmichael numbers.
  134. ;
  135.  
  136. (defun prime1p (p)
  137.   (or (= p 2)
  138.       (= p 3)
  139.       (= p 5)
  140.       (and (> p 1)
  141.            (= 1 (mexpt p 2 (1- p)))
  142.            (= 1 (mexpt p 3 (1- p)))
  143.            (= 1 (mexpt p 5 (1- p)))
  144.            'maybe)))
  145.  
  146.  
  147.  
  148. ;
  149. ;This primality test uses the Miller-Rabin test to check whether a number is
  150. ;prime.  This test may falsely assert that a number is prime with a probability
  151. ;no greater than 2^(-2*k), where k is the number of iterations.  If k=32, the
  152. ;probability of a wrong primality answer is no greater than 2^-64; actually, the
  153. ;probability is much smaller than this.
  154. ;k can be set by changing the *miller-iteration-count* global.
  155. ;
  156.  
  157. ;Return nil if p is not a prime, and t if it is (may be wrong with probability
  158. ;as specified above).  Return maybe if this test has been turned off.
  159.  
  160. (defvar *miller-iteration-count* 32)
  161.  
  162. (defun prime2p (n)
  163.   (cond
  164.    ((<= *miller-iteration-count* 0) 'maybe)
  165.    ((< n 2) nil)
  166.    ((= n 2) t)
  167.    ((evenp n) nil)
  168.    (t (let ((minusone (- n 1)))
  169.         (multiple-value-bind (s tt) (odd-shift minusone)
  170.           (dotimes (i *miller-iteration-count* t)
  171.             (let ((bb (mexpt n (1+ (random minusone)) tt)))
  172.               (unless (or (= bb 1) (= bb minusone))
  173.                 (do ((b (msquare n bb) (msquare n b))
  174.                      (j 1 (1+ j)))
  175.                     ((= b minusone))
  176.                   (when (or (= b 1) (> j s))
  177.                     (return-from prime2p nil)))))))))))
  178.  
  179. ;Return s and t such that n=t*2^s with t odd.
  180. (defun odd-shift (n)
  181.   (do ((tt n (/ tt 2))
  182.        (s 0 (1+ s)))
  183.       ((oddp tt) (values s tt))))
  184.  
  185. ;Return t if the prime tests test1 and test2 are equivalent on p.
  186. (defun equal-testp (p test1 test2)
  187.   (eq (not (funcall test1 p)) (not (funcall test2 p))))
  188.  
  189. ;Check that the prime tests test1 and test2 are equivalent over a range of
  190. ;numbers starting at n.
  191. (defun equal-test-range (n test1 test2)
  192.   (let ((t1 (funcall test1 n))
  193.         (t2 (funcall test2 n)))
  194.     (if t1 (display* n))
  195.     (unless (eq (not t1) (not t2)) (cerror "Search will resume" "Fail on ~D" n))
  196.     (equal-test-range (1+ n) test1 test2)))
  197.  
  198. (defvar prime-procedures (list #'prime0p #'prime2p))
  199.  
  200. ;
  201. ;Test whether p is a prime.  Return true, false, or maybe.
  202.  
  203. (defun prime? (p)
  204.   (prime-procedures? p prime-procedures))
  205.  
  206. (defun prime-procedures? (p procs)
  207.   (if (endp procs) 'maybe
  208.       (let ((answer (funcall (car procs) p)))
  209.         (if (eq answer 'maybe)
  210.           (prime-procedures? p (cdr procs))
  211.           answer))))
  212.  
  213. ;
  214. ;Find the smallest prime greater than or equal to n.
  215. ;
  216.  
  217. (defun next-prime (n)
  218.   (cond ((<= n 2) 2)
  219.         ((evenp n) (next-prime (1+ n)))
  220.         ((prime? n) n)
  221.         (t (next-prime (+ n 2)))))
  222.  
  223.  
  224.  
  225. ;*****************
  226. ;* Factorization *
  227. ;*****************
  228.  
  229. ;
  230. ;FactorList procedures.
  231. ;A FactorList is a partial factorization that consists of two lists:
  232. ;factors that are not necessarily primes and factors that are known to be
  233. ;prime.
  234. ;
  235.  
  236. ;Create a FactorList with number n and no factors.
  237. (proclaim '(inline new-primes-flist new-factors-flist add-prime-flist))
  238. (defmacro new-primes-flist (&rest primes)
  239.   (list 'list (cons 'list primes)))
  240. (defmacro new-factors-flist (&rest numbers)
  241.   (cons 'list (cons nil numbers)))
  242.  
  243. (defmacro make-flist (primes factors) `(cons ,primes ,factors))
  244.  
  245. (defmacro primes-flist (flist) `(car ,flist))
  246. (defmacro factors-flist (flist) `(cdr ,flist))
  247.  
  248. (defun add-prime-flist (p flist)
  249.   (make-flist (cons p (primes-flist flist))
  250.               (factors-flist flist)))
  251.  
  252. (defun merge-lists (list1 list2)
  253.   (cond ((endp list1) list2)
  254.         ((endp list2) list1)
  255.         ((<= (car list1) (car list2))
  256.          (cons (car list1) (merge-lists (cdr list1) list2)))
  257.         (t (cons (car list2) (merge-lists list1 (cdr list2))))))
  258.  
  259. (defun merge-flists (flist1 flist2)
  260.   (make-flist (merge-lists (primes-flist flist1) (primes-flist flist2))
  261.               (merge-lists (factors-flist flist1) (factors-flist flist2))))
  262.  
  263. ;
  264. ;This factoring program attempts to factor n by checking whether it is a
  265. ;prime.  If so, it flags it as such.
  266. ;
  267.  
  268. (defun factor0 (n)
  269.   (if (prime? n) (new-primes-flist n)
  270.       (new-factors-flist n)))
  271.  
  272. ;
  273. ;This is a quick factoring program that factors small primes out of p.
  274. ;This test returns a FactorList.
  275. ;
  276.  
  277. (defun factor1-primes (n primes)
  278.   (if (endp primes) (new-factors-flist n)
  279.       (let ((prime (car primes)))
  280.         (cond ((> (square prime) n) (new-primes-flist n))
  281.               ((zerop (rem n prime))
  282.                (add-prime-flist prime (factor1-primes (floor n prime) primes)))
  283.               (t (factor1-primes n (cdr primes)))))))
  284.  
  285. (defun factor1 (n)
  286.   (if (= n 1) (new-factors-flist n)
  287.       (factor1-primes n small-primes)))
  288.  
  289.  
  290. ;
  291. ;This is a Pollard rho factoring program.
  292. ;
  293.  
  294. (defvar *visible-rho-factor* t)
  295.  
  296. (defun rho-factor1 (n) (rho-factor n 1))
  297. (defun rho-factor3 (n) (rho-factor n 3))
  298.  
  299. (defun rho-factor (n coeff)
  300.   (if (< n 4) (new-factors-flist n)
  301.       (rho-factor-sub n coeff 1 1 1 1 2 256)))
  302.  
  303. (defun rho-factor-sub (n coeff x1 x2 c1 c2 climit step)
  304.   (defun iterate (x1 xref count)
  305.     (do ((product 1 (rem (* product (abs (- x xref)) product) n))
  306.          (x x1)
  307.          (i count (1- i)))
  308.         ((zerop i) (values x (gcd product n)))
  309.       (setq x (rem (+ (square x) coeff) n))))
  310.   (if *visible-rho-factor* (format t "[~D] " c1))
  311.   (let ((count (min (- climit c1) step)))
  312.     (multiple-value-bind (x g) (iterate x1 x2 count)
  313.       (cond ((= 1 g)
  314.              (if (= climit (+ c1 count))
  315.                (rho-factor-sub n coeff x x climit climit (+ climit climit) step)
  316.                (rho-factor-sub n coeff x x2 (+ c1 count) c2 climit step)))
  317.             ((= n g)
  318.              (if (= step 1)
  319.                (new-factors-flist n)
  320.                (rho-factor-sub n coeff x1 x2 c1 c2 climit (max 1 (floor step 16)))))
  321.             (t (new-factors-flist g (floor n g)))))))
  322.  
  323.  
  324. (defvar factor-procedures (list #'factor1 #'factor0 #'rho-factor1 #'rho-factor3))
  325.  
  326. ;;; Factor n and return a list of factors.
  327. (defun factor (n)
  328.   (let ((l (factor-flist n)))
  329.     (if (endp (cdr l)) (car l)
  330.         (cerror "" "Unable to factor ~D: ~S" n l))))
  331.  
  332. ;;; Factor n and return a factorization of n consisting of either lone factors
  333. ;;; or sublists of the form (p e) to indicate that p^e is a factor of n.  The
  334. ;;; factors are in increasing order and are not repeated.
  335.  
  336. (defun factorlist->ilist (factorlist)
  337.   (if (null factorlist) ()
  338.       (do
  339.         ((first (car factorlist))
  340.          (fl (cdr factorlist) (cdr fl))
  341.          (count 1 (1+ count)))
  342.         ((or (endp fl) (/= first (car fl)))
  343.          (if (= count 1) (cons first (factorlist->ilist fl))
  344.              (acons first count (factorlist->ilist fl)))))))
  345.          
  346. (defun factor-ilist (n)
  347.   (factorlist->ilist (factor n)))
  348.  
  349. ;
  350. ;Factor n and return a FactorList.
  351. ;
  352.  
  353. (defun factor-flist (n)
  354.   (procs-factor n factor-procedures))
  355.  
  356. (defvar *visible-factor* t)
  357.  
  358. (defun procs-factor (n procs)
  359.   (if (endp procs) (new-factors-flist n)
  360.       (progn
  361.         (if *visible-factor*
  362.           (format t "Factoring ~D using ~S... " n (car procs)))
  363.         (let ((factoring (funcall (car procs) n)))
  364.           (if *visible-factor*
  365.             (format t "~S~%" factoring))
  366.           (cond ((null (factors-flist factoring)) factoring)
  367.                 ((= (car (factors-flist factoring)) n)
  368.                  (procs-factor n (cdr procs)))
  369.                 (t (merge-flists
  370.                     (make-flist (primes-flist factoring) nil)
  371.                     (reduce #'merge-flists
  372.                             (mapcar #'factor-flist (factors-flist factoring))))))))))
  373.  
  374. (defun fast-factor-sub (n k primes)
  375.   (let ((prime-limit (square (next-prime (car (last primes))))))
  376.     (defun check (n)
  377.       (defun factor-power (prime)
  378.         (if (zerop (rem n prime))
  379.           (progn
  380.             (setq n (floor n prime))
  381.             (1+ (factor-power prime)))
  382.           0))
  383.       (let ((powers (mapcar #'factor-power primes)))
  384.         (if (< n prime-limit)
  385.           (list powers n)
  386.           nil)))
  387.     (let* ((r (floor (sqrt n)))
  388.            (2r (* 2 r))
  389.            (new-v)
  390.            (new-a))
  391.       (format t "Factor: n=~D k=~D r=~D primes=~S~%" n k r primes)
  392.       (do ((old-u 2r u)
  393.            (u 2r (- 2r (mod u new-v)))
  394.            (old-v (- (* n k) (square r)) v)
  395.            (v 1 new-v)
  396.            (a 0 new-a)
  397.            (old-p 1 p)
  398.            (p r (mod (+ old-p (* new-a p)) n))
  399.            (s 1 (- s))
  400.            (count 0 (1+ count)))
  401.           (nil)
  402.         (format t "Iteration ~D: u=~D v=~D a=~D p=~D s=~D " count u v a old-p s)
  403.         (prin1 (check v))
  404.         (terpri)
  405.         (setq new-v (+ old-v (* a (- old-u u))))
  406.         (setq new-a (floor u new-v))))))
  407.  
  408. (defun phi (n) (phi-ilist (factor-ilist n)))
  409. (defun phi-ilist (ilist)
  410.   (cond ((null ilist) 1)
  411.         ((numberp (car ilist)) (* (1- (car ilist)) (phi-ilist (cdr ilist))))
  412.         (t (* (1- (caar ilist)) (expt (caar ilist) (1- (cdar ilist)))
  413.               (phi-ilist (cdr ilist))))))
  414.  
  415. (defun jacobi (num den)
  416.   (defun internal-jacobi (num den factor)
  417.     (cond
  418.      ((>= num den) (internal-jacobi (mod num den) den factor))
  419.      ((= num 1) factor)
  420.      ((evenp num) (internal-jacobi (/ num 2) den
  421.                                    (if (eq (logbitp 1 den) (logbitp 2 den))
  422.                                      factor
  423.                                      (- factor))))
  424.      ((evenp den) (internal-jacobi num (/ den 2) factor))
  425.      (t (internal-jacobi den num
  426.                          (if (and (logbitp 1 num) (logbitp 1 den))
  427.                            (- factor)
  428.                            factor)))))
  429.   (cond
  430.    ((/= (gcd num den) 1) 0)
  431.    ((< num 0) (internal-jacobi (mod num den) den 1))
  432.    (t (internal-jacobi num den 1))))
  433.  
  434. (defun jacobi-check (num den)
  435.   (eq (mod (jacobi num den) den) (mexpt den num (/ (1- den) 2))))
  436.  
  437. (defun generator? (g p &optional p-ilist)
  438.   (defun generator-check (g p p-ilist)
  439.     (cond
  440.      ((null p-ilist) t)
  441.      ((= (mexpt p g (/ (1- p) (if (numberp (car p-ilist)) (car p-ilist) (caar p-ilist)))) 1)
  442.       nil)
  443.      (t (generator-check g p (cdr p-ilist)))))
  444.   (cond
  445.    ((null p-ilist) (generator? g p (factor-ilist (1- p))))
  446.    ((/= (gcd g p) 1) nil)
  447.    (t (generator-check g p p-ilist))))
  448.  
  449. (defun next-generator (g p &optional p-ilist)
  450.   (cond
  451.    ((null p-ilist) (next-generator g p (factor-ilist (1- p))))
  452.    ((generator? g p p-ilist) g)
  453.    (t (next-generator (1+ g) p p-ilist))))
  454.  
  455. (defun next-prime-with-gen (g p)
  456.   (let ((prime (next-prime p)))
  457.     (if (generator? g prime) prime
  458.         (next-prime-with-gen g (1+ prime)))))
  459.  
  460. ;(factor 3463544557620305157)
  461. ;(factor 80209029642225101201) ==> (8872758161 9039920641) [150784 iterations]
  462.  
  463.  
  464. (defvar *visible-rho-ind* t)
  465.  
  466. (defun rho-ind (a g p)
  467.   (let ((low-third (floor p 3))
  468.         (high-third (floor (* 2 p) 3))
  469.         (phi (1- p)))
  470.     (defun rho (xlist)
  471.       (let ((x (car xlist)))
  472.         (cond
  473.          ((<= x low-third)
  474.           (list (m* p a x) (mod (1+ (cadr xlist)) phi) (caddr xlist)))
  475.          ((<= x high-third)
  476.           (list (msquare p x) (m* phi 2 (cadr xlist)) (m* phi 2 (caddr xlist))))
  477.          (t
  478.           (list (m* p g x) (cadr xlist) (mod (1+ (caddr xlist)) phi))))))
  479.     (do
  480.       ((x (rho '(1 0 0)) (rho x))
  481.        (xn 1 (1+ xn))
  482.        (y (rho (rho '(1 0 0))) (rho (rho y)))
  483.        (yn 2 (+ 2 yn)))
  484.       ((progn
  485.          (if *visible-rho-ind*
  486.            (format t "x~D = ~D = a^~D*g^~D, x~D = ~D = a^~D*g^~D~%"
  487.                    xn (car x) (cadr x) (caddr x)
  488.                    yn (car y) (cadr y) (caddr y)))
  489.          (= (car x) (car y)))
  490.        (let ((aexp (- (cadr x) (cadr y)))
  491.              (gexp (- (caddr y) (caddr x))))
  492.          (format t "a^~D = g^~D~%" aexp gexp)
  493.          (multiple-value-bind (b c aexp) (euclid aexp phi)
  494.            (let ((gexp (m* phi gexp b)))
  495.              (format t "a^~D = g^~D~%" aexp gexp))))))))
  496.  
  497.  
  498. ;*******
  499. ;* RSA *
  500. ;*******
  501.  
  502. ;Find a prime number using start as a true random number seed.
  503. ;The prime returned is congruent to 2 modulo 3.
  504.  
  505. (defun find-rsa-prime (start)
  506.   (do ((p (+ 5 (* start 6)) (+ p 6)))
  507.       ((prime? p) p)))
  508.  
  509. ;Generate an RSA encoding key-decoding key pair.
  510. ;The two inputs should be random numbers from which the prime number search
  511. ;will begin.  Start1 and start2 should have approximately half as many digits
  512. ;as E and D.  Start1 and start2 should be different; the ratio of start1 and
  513. ;start2 should not be close to an exact fraction.  In a real application a few
  514. ;further precautions should be taken, as discussed in Knuth's volume 2.
  515. ;Return two values:  the modulus E and the decrypting key D.
  516.  
  517. (defun make-rsa (start1 start2)
  518.   (let ((p (find-rsa-prime start1))
  519.         (q (find-rsa-prime start2)))
  520.     (let ((e (* p q)))
  521.       (multiple-value-bind (x y g) (euclid 3 (* (1- p) (1- q)))
  522.         (unless (= g 1)
  523.           (error "3 and (p-1)(q-1) should be relatively prime."))
  524.         (when (< x 0) ;Make x positive if necessary.
  525.           (setq x (+ x (* (1- p) (1- q)))))
  526.         (values e x)))))
  527.  
  528.  
  529. ;Encrypt the plaintext using the encrypting key E.
  530.  
  531. (defun encrypt-rsa (E plaintext)
  532.   (when (< (square plaintext) E)
  533.     (format t "Warning: plaintext is too short.~%"))
  534.   (when (>= plaintext E)
  535.     (format t "Warning: plaintext is too long; information was lost.~%"))
  536.   (mexpt E plaintext 3))
  537.  
  538. ;Decrypt the cyphertext using the decrypting key D.
  539.  
  540. ;The encrypting key E is also needed.
  541. (defun decrypt-rsa (E D cyphertext)
  542.   (mexpt E cyphertext D))
  543.